using System;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;

public class CameraManager : MonoBehaviour
{
    private float lastDistanceToNextWaypoint;
    private Vector3 lastWaypoint, nextWaypoint;
    private PlayerControlJnR pjr;
    private List<Waypoint> waypoints;

    private void Start()
    {
        InitializeWaypoints();

        this.pjr = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerControlJnR>();

        if (Player.Object != null)
            transform.position = CalculateCameraPosition();
    }

    private void Update()
    {
        //TODO: kamera debug entfernen
        for (int i = 0; i < waypoints.Count - 1; i++)
        {
            Debug.DrawLine(waypoints[i].Coordinates, waypoints[i + 1].Coordinates, Color.red);
        }

        CheckWaypoints();

        if (Player.Object == null) return;

        transform.position = CalculateCameraPosition();
    }

    private Vector3 CalculateCameraPosition()
    {
        float y;
        if (this.nextWaypoint != this.lastWaypoint)
        {
            float distY = this.nextWaypoint.y - this.lastWaypoint.y;
            float distX = this.nextWaypoint.x - this.lastWaypoint.x;
            float distXCamLast = transform.position.x - this.lastWaypoint.x;

            y = distXCamLast * distY / distX;
        }
        else
        {
            Vector3 tempNextWp = Vector3.zero;
            switch (this.pjr.CurrentDirection)
            {
                case MovementDirection.Left:
                    for (int i = 0; i < this.waypoints.Count; i++)
                    {
                        if (this.waypoints[i].Coordinates == this.lastWaypoint && i < this.waypoints.Count - 1)
                        {
                            tempNextWp = this.waypoints[i + 1].Coordinates;
                        }
                    }
                    break;
                case MovementDirection.Right:
                    for (int i = 0; i < this.waypoints.Count; i++)
                    {
                        if (this.waypoints[i].Coordinates == this.lastWaypoint && i > 0)
                        {
                            tempNextWp = this.waypoints[i - 1].Coordinates;
                        }
                    }
                    break;
            }

            float distY = tempNextWp.y - this.lastWaypoint.y;
            float distX = tempNextWp.x - this.lastWaypoint.x;
            float distZCamLast = transform.position.x - this.lastWaypoint.x;

            y = distZCamLast * distY / distX;
        }

        return new Vector3(Player.Object.transform.position.x + 2.25f, this.lastWaypoint.y + y,
                           transform.position.z);
    }

    private void InitializeWaypoints()
    {
        GameObject[] waypointsG = GameObject.FindGameObjectsWithTag("Waypoint");
        this.waypoints = new List<Waypoint>();

        foreach (GameObject go in waypointsG)
        {
            GameObject parent = go.transform.parent.gameObject;

            string[] nameParts = parent.name.Split('_');

            float offsetX = parent.transform.position.x == 0 ? 0 : parent.transform.renderer.bounds.size.x;
            float offsetY = nameParts.Length >= 5 ? int.Parse(nameParts[4][0].ToString()) : parent.renderer.bounds.size.y;

            Vector3 newWaypoint = new Vector3(parent.transform.position.x + offsetX,
                                       parent.transform.position.y + offsetY + 2,
                                       parent.transform.position.z - parent.renderer.bounds.size.z / 1.5f);

            this.waypoints.Add(new Waypoint(newWaypoint, parent.name));
        }

        waypoints = waypoints.OrderBy(cw => cw.Coordinates.x).ToList();

        transform.position = this.waypoints[0].Coordinates;
        this.lastWaypoint = this.waypoints[0].Coordinates;
        this.nextWaypoint = this.waypoints[1].Coordinates;
    }

    private void CheckWaypoints()
    {
        switch (this.pjr.CurrentDirection)
        {
            case MovementDirection.Left:

                #region movingToLeft

                if (transform.position.x < this.nextWaypoint.x)
                {
                    for (int i = 0; i < this.waypoints.Count; i++)
                    {
                        if (this.waypoints[i].Coordinates != this.nextWaypoint || i <= 0) continue;
                        this.nextWaypoint = this.waypoints[i - 1].Coordinates;
                        break;
                    }
                }
                else if (transform.position.x > this.nextWaypoint.x)
                {
                    if (Vector3.Distance(transform.position, this.nextWaypoint) < 0.5)
                    {
                        for (int i = 0; i < this.waypoints.Count; i++)
                        {
                            if (this.waypoints[i].Coordinates != this.nextWaypoint || i <= 0) continue;
                            this.lastWaypoint = this.waypoints[i].Coordinates;
                            this.nextWaypoint = this.waypoints[i - 1].Coordinates;
                            break;
                        }
                    }
                }

                #endregion

                break;
            case MovementDirection.Right:

                #region movingToRight

                if (transform.position.x > this.nextWaypoint.x)
                {
                    for (int i = 0; i < this.waypoints.Count; i++)
                    {
                        if (this.waypoints[i].Coordinates != this.nextWaypoint || i >= this.waypoints.Count - 1)
                            continue;
                        this.nextWaypoint = this.waypoints[i + 1].Coordinates;
                        break;
                    }
                }
                else if (transform.position.x < this.nextWaypoint.x)
                {
                    if (Vector3.Distance(transform.position, this.nextWaypoint) < 0.5)
                    {
                        for (int i = 0; i < this.waypoints.Count; i++)
                        {
                            if (this.waypoints[i].Coordinates != this.nextWaypoint || i >= this.waypoints.Count - 1)
                                continue;
                            this.lastWaypoint = this.waypoints[i].Coordinates;
                            this.nextWaypoint = this.waypoints[i + 1].Coordinates;
                            break;
                        }
                    }
                }

                #endregion

                break;
        }
    }
}